package com.cgfay.facedetect.engine.mediapipes

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.cgfay.facedetect.engine.FaceTrackParam
import com.cgfay.facedetect.engine.FaceTrackerBuilder
import com.cgfay.facedetect.engine.IFaceTracker
import com.cgfay.facedetect.listener.FaceTrackerCallback
import com.cgfay.facedetect.utils.ConUtil
import com.cgfay.facedetect.utils.SensorEventUtil
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock

class MediaPipeFaceTracker : IFaceTracker {

    private val TAG = MediaPipeFaceTracker::class.java.simpleName
    private val VERBOSE = false

//    private val mSyncFence = Any()
    private val mSyncFence = ReentrantLock()

    // 人脸检测参数
    private var mFaceTrackParam: FaceTrackParam = FaceTrackParam.getInstance()

    // 检测线程
    private var mTrackerThread: TrackerThread? = null

    private constructor()

    companion object {
        private var tracker : MediaPipeFaceTracker? = null
        @JvmStatic
        fun instance(): MediaPipeFaceTracker {
            if (tracker == null) {
                tracker = MediaPipeFaceTracker()
            }
            return tracker!!
        }
    }

    /**
     * 准备检测器
     * 启动检测线程
     */
    override fun initTracker() {
        mSyncFence.withLock {
            mTrackerThread = TrackerThread("MediaPipeFaceTrackerThread").apply {
                start()
                waitUntilReady()
            }
        }
    }

    /**
     * 初始化人脸检测
     * @param context       上下文
     * @param orientation   图像角度
     * @param width         图像宽度
     * @param height        图像高度
     */
    override fun prepareFaceTracker(context: Context?, orientation: Int, width: Int, height: Int) {
        mSyncFence.withLock {
            if (context != null) {
                mTrackerThread?.prepareFaceTracker(context, orientation, width, height)
            }
        }
    }

    /**
     * 检测人脸
     * @param data
     * @param width
     * @param height
     */
    override fun trackFace(data: ByteArray?, width: Int, height: Int) {
        mSyncFence.withLock {
            if (data != null) {
                mTrackerThread?.trackFace(data, width, height)
            } else {
                Log.d(TAG, "trackFace, data is null")
            }
        }
    }

    override fun destroyTracker() {
        mSyncFence.withLock {
            mTrackerThread?.quitSafely()
        }
    }

    override fun setFaceCallback(callback: FaceTrackerCallback?): FaceTrackerBuilder {
//        return FaceTrackerBuilder(this, callback)
        return FaceTrackerBuilder.instance().registCallback(callback)
    }

    override fun setBackCamera(backCamera: Boolean): IFaceTracker {
        mFaceTrackParam.isBackCamera = backCamera
        return this
    }

    override fun enable3DPose(enable: Boolean): IFaceTracker {
        mFaceTrackParam.enable3DPose = enable
        return this
    }

    override fun enableROIDetect(enable: Boolean): IFaceTracker {
        mFaceTrackParam.enable3DPose = enable
        return this
    }

    override fun enable106Points(enable: Boolean): IFaceTracker {
        mFaceTrackParam.enable3DPose = enable
        return this
    }

    override fun enableMultiFace(enable: Boolean): IFaceTracker {
        mFaceTrackParam.enable3DPose = enable
        return this
    }

    override fun enableFaceProperty(enable: Boolean): IFaceTracker {
        mFaceTrackParam.enable3DPose = enable
        return this
    }

    override fun minFaceSize(size: Int): IFaceTracker {
        mFaceTrackParam.minFaceSize = size
        return this
    }

    override fun detectInterval(interval: Int): IFaceTracker {
        mFaceTrackParam.detectInterval = interval
        return this
    }

    override fun trackMode(mode: Int): IFaceTracker {
        mFaceTrackParam.trackMode = mode
        return this
    }


    /****
     * 脸部关键点检测线程
     */
    class TrackerThread(val _name:String) : Thread(_name) {
        val mStartLock = ReentrantLock()
        val condition = mStartLock.newCondition()
        var mReady : Boolean = false
        var mSensorUtil: SensorEventUtil? = null
        var mLooper: Looper? = null
        var mHandler: Handler? = null
        /** 线程循环 */
        override fun run() {
            super.run()
            Looper.prepare()
            synchronized(this) {
                mLooper = Looper.myLooper()
                mHandler = Handler(mLooper!!)
            }
            mStartLock.withLock {
                mReady = true
                condition.signalAll()
            }
            Looper.loop()
            synchronized(this) {
                release()
                mHandler?.removeCallbacksAndMessages(null)
                mHandler = null
            }
            mStartLock.withLock {
                mReady = false
            }
        }

        /****
         * 阻塞等待looper轮询准备好
         */
        fun waitUntilReady() {
            mStartLock.withLock {
                while (!mReady) {
                    try {
                        condition.await()
                    }catch (ex:IllegalStateException) {
                    }
                }
            }
        }

        /****
         * 安全退出
         */
        fun quitSafely() : Boolean {
            if (mLooper != null)  {
                mLooper!!.quitSafely()
                return true
            }
            return false
        }

        /****
         * 准备好面部识别
         */
        fun prepareFaceTracker(context:Context, orientation:Int, width:Int, height:Int) {
            waitUntilReady()
            mHandler?.post{
                internalPrepareFaceTracker(context, orientation, width, height)
            }
        }

        private fun internalPrepareFaceTracker(
            context: Context,
            orientation: Int,
            width: Int,
            height: Int
        ) {
//            TODO("Not yet implemented")
        }

        /******
         * 检测人脸关键点
         * @param data      图像数据， NV21 或者 RGBA格式
         * @param width     图像宽度
         * @param height    图像高度
         */
        fun trackFace(nv21bytes: ByteArray, width:Int, height:Int) {
            waitUntilReady()
            mHandler?.post{
                internalTrackFace(nv21bytes, width, height)
            }
        }

        private fun internalTrackFace(nv21bytes: ByteArray, width: Int, height: Int) {
//            TODO("Not yet implemented")
        }

        /****
         * 释放资源
         */
        fun release(){
            ConUtil.releaseWakeLock()
            //TODO
        }
    }
}